package com.ay.weixin.fdc.boss.menu.event;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;

import org.lizar.config.Config;
import org.lizar.config.keys.Keys;
import org.lizar.controller.Event;
import org.lizar.controller.loader.EventLoader;
import org.lizar.ioc.Container;
import org.lizar.json.JList;
import org.lizar.json.JObject;
import org.lizar.json.util.JSONParser;
import org.lizar.log.Log;
import org.lizar.log.Logger;
import org.lizar.util.StringHelper;
import org.lizar.util.https.Https;

import com.ay.weixin.autoreply.db.IbatisAutoReplyDao;
import com.ay.weixin.autoreply.db.IbatisAutoReplyNewsDao;
import com.ay.weixin.autoreply.domain.AccessTokenModule;
import com.ay.weixin.autoreply.domain.Message;
import com.ay.weixin.autoreply.domain.MsgNews;
import com.ay.weixin.fdc.admin.customer.domain.Customer;
import com.ay.weixin.fdc.boss.customer.event.CustomerLogin;
import com.ay.weixin.fdc.boss.menu.db.IbatisMenuDao;
import com.ay.weixin.fdc.boss.menu.db.IbatisMenuSubDao;
import com.ay.weixin.fdc.boss.menu.domain.Menu;
import com.ay.weixin.fdc.boss.menu.domain.MenuSub;

public class MenuEvt extends Event {

	private Log log=Logger.newInstance(this.getClass());
	
	private IbatisMenuDao menu_dao;
	
	private IbatisMenuSubDao menu_sub_dao;
	
	private AccessTokenModule access_token_module;
	
	private IbatisAutoReplyDao auto_reply_dao;
	private IbatisAutoReplyNewsDao auto_reply_news_dao;
	
	@Override
	public void init_property() throws Exception {
		menu_dao=Container.get(IbatisMenuDao.class);
		menu_sub_dao=Container.get(IbatisMenuSubDao.class);
		access_token_module=Container.get(AccessTokenModule.class);
		auto_reply_dao=Container.get(IbatisAutoReplyDao.class);
		auto_reply_news_dao=Container.get(IbatisAutoReplyNewsDao.class);
		
	}

	@Override
	public String default_handling_path() {
		return "/menu/*";
	}

	@Override
	public void handle(EventLoader el) throws ServletException, IOException {
		Customer adm=(Customer)el.getSessionAttr("customer");
		if(adm==null){
			el.response_to_root(CustomerLogin.login_path());
		}else{
			el.setAttr("Max_Menu_Number",3);
			el.setAttr("Max_Sub_Menu_Number",5);
			if(StringHelper.equals(el.queryPath(1),"")){
				load_menu(el,adm.getWxprojectID());
			}else if(StringHelper.equals(el.queryPath(1),"add")){
				add(el,adm.getWxprojectID());
			}else if(StringHelper.equals(el.queryPath(1),"add_new")){
				el.template("/WEB-INF/template/boss/menu/menu_add.vm");
			}else if(StringHelper.equals(el.queryPath(1),"update")){
				update(el,adm.getWxprojectID());
			}else if(StringHelper.equals(el.queryPath(1),"delete")){
				delete(el,adm.getWxprojectID());
			}else if(StringHelper.equals(el.queryPath(1),"commit")){
				commit(el,adm.getWxprojectID());
			}else if(StringHelper.equals(el.queryPath(1),"commit_view")){
				commit_view(el,adm.getWxprojectID());
			}else if(StringHelper.equals(el.queryPath(1),"commit_delete")){
				commit_delete(el,adm.getWxprojectID());
			}else if(StringHelper.equals(el.queryPath(1),"sub")){
				if(StringHelper.equals(el.queryPath(2),"")){
					load_menu_sub(el,adm.getWxprojectID());
				}else if(StringHelper.equals(el.queryPath(2),"add")){
					add_menu_sub(el,adm.getWxprojectID());
				}else if(StringHelper.equals(el.queryPath(2),"add_new")){
					to_add_sub_page(el,adm.getWxprojectID());
				}else if(StringHelper.equals(el.queryPath(2),"update")){
					update_menu_sub(el,adm.getWxprojectID());
				}else if(StringHelper.equals(el.queryPath(2),"delete")){
					sub_delete(el,adm.getWxprojectID());
				}else if(StringHelper.equals(el.queryPath(2),"detail")){
					load_sub_detail(el,adm.getWxprojectID());
				}
			}
		}
	}
	

	private void commit_view(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=abstractMenu(el,wxproject_id);
		if(msg!=null){
			el.setAttr("msg",msg);
			load_menu(el,wxproject_id);
			return;
		}
		String access_token=access_token_module.getAccessToken(wxproject_id);
		if(access_token==null){
			el.setAttr("msg",el.i18("menu.update.accesstoken.getfailure"));
			load_menu(el,wxproject_id);
			return;
		}
		StringBuilder result=new StringBuilder();
		result.append(el.getAttr("menus").toString());
		String url=String.format(Keys.getStr("URL_TO_QUERY_MENU"), access_token);
		msg=Https.GetMethod(url);
		result.append("<br/>");
		result.append(msg);
		el.setAttr("msg",result.toString());
		load_menu(el,wxproject_id);
	}
	
	private void commit_delete(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=abstractMenu(el,wxproject_id);
		if(msg!=null){
			el.setAttr("msg",msg);
			load_menu(el,wxproject_id);
			return;
		}
		String access_token=access_token_module.getAccessToken(wxproject_id);
		if(access_token==null){
			el.setAttr("msg",el.i18("menu.update.accesstoken.getfailure"));
			load_menu(el,wxproject_id);
			return;
		}
		StringBuilder result=new StringBuilder();
		result.append(el.getAttr("menus").toString());
		String url=String.format(Keys.getStr("URL_TO_DELETE_MENU"), access_token);
		msg=Https.GetMethod(url);
		result.append("<br/>");
		result.append(msg);
		el.setAttr("msg",result.toString());
		load_menu(el,wxproject_id);
	}
	
	public void load_sub_detail(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String pkey=el.getStr("parent_key");
		String key=el.getStr("key");
		String msg=el.getAttr("msg", null);
		
		try {
			MenuSub smenu=menu_sub_dao.get(wxproject_id,pkey,key);
			el.setAttr("parent_key", pkey);
			el.setAttr("smenu", smenu);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
		}
		
		try {
			Message message = auto_reply_dao.getCLICKMessage(wxproject_id,"type_msg",key);
			el.setAttr("reply_msg", message);
			List<MsgNews> list=auto_reply_news_dao.getNewsListByKey(wxproject_id,key);
			el.setAttr("reply_news", list);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
		}
		
		
		el.setAttr("msg", msg);
		el.template("/WEB-INF/template/boss/menu/menu_sub_detail.vm");
		
	}
	
	
	private void commit(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=abstractMenu(el,wxproject_id);
		if(msg!=null){
			el.setAttr("msg",msg);
			load_menu(el,wxproject_id);
			return;
		}
		String access_token=access_token_module.getAccessToken(wxproject_id);
		if(access_token==null){
			el.setAttr("msg",el.i18("menu.update.accesstoken.getfailure"));
			load_menu(el,wxproject_id);
			return;
		}
		
		String url=String.format(Keys.getStr("URL_TO_CREATE_MENU"), access_token);
		//msg=Https.PostMethod(url,men.toString());
		msg=Https.PostMethod(url,el.getAttr("menus").toString());
		JObject obj=null;
		try{
			 obj=(JObject)JSONParser.parse(msg);
		}catch(Exception e){
			el.setAttr("msg",msg);
			load_menu(el,wxproject_id);
			return;
		}
		log.info(msg);
		if(obj!=null){
			int code=obj.getInt("errcode");
			switch(code){
			case 0:
				msg="操作成功";
				break;
			case -1:
				msg="微信服务器繁忙";
				break;
			default :
				if(code>=40015&&code<=40028){
					msg="菜单数据有问题，请再次检查，错误码:"+code;
				}
			}
		}
		el.setAttr("msg",msg);
		load_menu(el,wxproject_id);
		
		
	}

	private String abstractMenu(EventLoader el,long wxproject_id){
		String msg=null;
		String result=null;
		List<Menu> list=null;
		try {
			list=menu_dao.getAllByWxprojectId(wxproject_id);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.update.db_failure");
			log.error(msg, e);
			return msg;
		}
		
		if(list==null||list.isEmpty()){
			msg=el.i18("menu.update.no.menu.found");
			return msg;
		}
		
		List<MenuSub> slist=null;
		try {
			slist=menu_sub_dao.getAllByWxprojectId(wxproject_id);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.update.db_failure");
			log.error(msg, e);
			return msg;
		}
		
		if(slist==null||slist.isEmpty()){
			result=toJSON(list);
			el.setAttr("menus", result);
			return null;
		}
		
		Iterator<Menu> itr=list.iterator();
		Menu cm=null;
		for(;itr.hasNext();){
			cm=itr.next();
			cm.setSubMenus(getSubMens(slist,cm.getKey()));
		}
		
		result=toJSON(list);
		el.setAttr("menus", result);
		return msg;
	}
	
	private String toJSON(List<Menu> list){
		JObject data=new JObject();
		JList l=new JList();
		data.put("button", l);
		Iterator<Menu> itr=list.iterator();
		Menu cm=null;
		int i=1;
		for(;itr.hasNext();){
			if(i>Keys.getInt("Max_Menu_Number")){
				log.warn("Menu max number is "+Keys.getInt("Max_Menu_Number")+",the excced one will be ignored.");
				break;
			}else{
				cm=itr.next();
				l.add(cm.toJSON());
			}
		}
		log.info("menus parsed:");
		log.info(data.to_beautifiergetStr());
		return data.toString();
		
	}
	
	
	private List<MenuSub> getSubMens(List<MenuSub> slist,String parentKey){
		List<MenuSub> selected_menu=null;
		Iterator<MenuSub> itr=slist.iterator();
		MenuSub msub=null;
		for(;itr.hasNext();){
			msub=itr.next();
			if(msub.getParent_key()==null){
				log.warn("menu_sub get a row which has no parent key:"+msub.getKey());
				itr.remove();
				continue;
			}
			if(msub.getParent_key().equals(parentKey)){
				if(selected_menu==null){
					selected_menu=new LinkedList<MenuSub>();
				}
				selected_menu.add(msub);
				itr.remove();
				continue;
			}
			
		}
		return selected_menu;
	}
	
	
	private void delete(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=null;
		String key=el.getStr("key");
		try {
			menu_dao.delete(wxproject_id,key);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.db.failure");
			el.setAttr("msg", msg);
		}
		if(msg==null){
			msg=el.i18("menu.delete.success");
		}
		el.setAttr("msg", msg);
		load_menu(el,wxproject_id);
	}
	
	private void sub_delete(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=null;
		String key=el.getStr("key");
		String parent_key=el.getStr("parent_key");
		try {
			menu_sub_dao.delete(wxproject_id,parent_key,key);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
			el.setAttr("msg", msg);
		}
		if(msg==null){
			msg=el.i18("menu.sub.delete.success");
		}
		el.setAttr("msg", msg);
		load_menu_sub(el,wxproject_id);
	}
	
	private String validate(EventLoader el,Menu menu){
		String msg=null;
		if(StringHelper.isNull(menu.getName())){
			msg=el.i18("menu.update.name.cannot.null");
			return msg;
		}
		
		if(menu.getName().length()>Keys.getInt("menu.name_max_length")){
			msg=String.format(el.i18("menu.update.name.maxlength.excceed"), Keys.getInt("menu.name_max_length"));
			return msg;
		}
		
		if(StringHelper.equals(menu.getType(), "click")&&StringHelper.isNull(menu.getKey())){
			msg=el.i18("menu.update.button.need.key");
			return msg;
		}
		if(StringHelper.equals(menu.getType(), "view")&&StringHelper.isNull(menu.getUrl())){
			msg=el.i18("menu.update.view.need.url");
			return msg;
		}
		
		if(menu.getName().length()>Keys.getInt("menu.key_max_length")){
			msg=String.format(el.i18("menu.update.key.maxlength.excceed"), Keys.getInt("menu.key_max_length"));
			return msg;
		}
		
		if(menu.getName().length()>Keys.getInt("menu.url_max_length")){
			msg=String.format(el.i18("menu.update.url.maxlength.excceed"), Keys.getInt("menu.url_max_length"));
			return msg;
		}
		
		return msg;
	}
	
	private String validate(EventLoader el,MenuSub menu){
		String msg=null;
		if(StringHelper.isNull(menu.getName())){
			msg=el.i18("menu.sub.update.name.cannot.null");
			return msg;
		}
		
		if(menu.getName().length()>Keys.getInt("menu_sub.name_max_length")){
			msg=String.format(el.i18("menu.sub.update.name.maxlength.excceed"), Keys.getInt("menu_sub.name_max_length"));
			return msg;
		}
		
		if(StringHelper.equals(menu.getType(), "click")&&StringHelper.isNull(menu.getKey())){
			msg=el.i18("menu.sub.update.button.need.key");
			return msg;
		}
		
		if(StringHelper.equals(menu.getType(), "view")&&StringHelper.isNull(menu.getUrl())){
			msg=el.i18("menu.sub.update.view.need.url");
			return msg;
		}
		
		if(menu.getName().length()>Keys.getInt("menu.key_max_length")){
			msg=String.format(el.i18("menu.sub.update.key.maxlength.excceed"), Keys.getInt("menu.key_max_length"));
			return msg;
		}
		
		if(menu.getName().length()>Keys.getInt("menu.url_max_length")){
			msg=String.format(el.i18("menu.sub.update.url.maxlength.excceed"), Keys.getInt("menu.url_max_length"));
			return msg;
		}
		
		return msg;
	}
	
	private void update(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=null;
		String key=el.getStr("key");
		if(StringHelper.isNull(key)){
			load_menu(el,wxproject_id);
			return;
		}
		String name=el.getStr("name");
		Menu menu=new Menu();
		boolean exist=false;
		try {
			exist = menu_dao.exist(wxproject_id,key);
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
		if(!exist){
			msg=String.format(el.i18("menu.not.exists"), key);
			el.setAttr("msg", msg);
			load_menu(el,wxproject_id);
			return;
		}
		menu.setName(name);
		menu.setKey(key);
		menu.setPos(el.getInt("pos"));
		menu.setType(el.getStr("type"));
		menu.setUrl(el.getStr("url"));
		menu.setWxproject_id(wxproject_id);
		msg=validate(el,menu);
		
		try {
			if(msg==null){
				menu_dao.update(menu);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.db.failure");
			el.setAttr("msg", msg);
		}
		if(msg==null){
			msg=el.i18("menu.update.success");
		}
		el.setAttr("msg", msg);
		load_menu(el,wxproject_id);
	}
	
	private void update_menu_sub(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=null;
		MenuSub menu=new MenuSub();
		String parent_key=el.getStr("parent_key");
		String key=el.getStr("key");
		menu.setParent_key(parent_key);
		menu.setKey(key);
		menu.setName(el.getStr("name"));
		boolean exist=false;
		try {
			exist = menu_sub_dao.exist(wxproject_id,parent_key,key);
		} catch (SQLException e1) {
			e1.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
			el.setAttr("msg", msg);
			load_sub_detail(el,wxproject_id);
			return;
		}
		if(!exist){
			msg=String.format(el.i18("menu.sub.not.exists"),parent_key, key);
			el.setAttr("msg", msg);
			load_sub_detail(el,wxproject_id);
			return;
		}
		menu.setPos(el.getInt("pos"));
		menu.setType(el.getStr("type"));
		menu.setUrl(el.getStr("url"));
		menu.setWxproject_id(wxproject_id);
		msg=validate(el,menu);
		try {
			if(msg==null){
				menu_sub_dao.update(menu);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
			el.setAttr("msg", msg);
		}
		if(msg==null){
			msg=el.i18("menu.sub.update.success");
		}
		el.setAttr("msg", msg);
		load_sub_detail(el,wxproject_id);
	}
	
	private void add(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=null;
		int menu_size=0;
		try {
			menu_size = menu_dao.size(wxproject_id);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.db.failure");
		}
		if(menu_size>=Keys.getInt("Max_Menu_Number")){
			msg=el.i18("menu.max.number.achieve");
		}
		if(msg!=null){
			el.setAttr("msg", msg);
			load_menu(el,wxproject_id);
			return;
		}
		String key=UUID.randomUUID().toString();
		try {
			if(menu_dao.exist(wxproject_id,key)){
				msg=String.format(el.i18("menu.exists"), key);
				el.setAttr("msg", msg);
				load_menu_sub(el,wxproject_id);
				return;
			}
		} catch (SQLException e1) {
			msg=el.i18("menu.db.failure");
			el.setAttr("msg", msg);
			load_menu_sub(el,wxproject_id);
			return;
		}
		Menu menu=new Menu();
		menu.setKey(key);
		menu.setName(el.getStr("name"));
		menu.setType(el.getStr("type"));
		menu.setUrl(el.getStr("url"));
		menu.setWxproject_id(wxproject_id);
		try {
			menu.setPos(menu_dao.getMaxPos(wxproject_id));
			msg=validate(el, menu);
			if(msg==null){
				menu_dao.insert(menu);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.db.failure");
			el.setAttr("msg", msg);
		}
		if(msg==null){
			msg=el.i18("menu.add.success");
		}
		load_menu(el,wxproject_id);
		
	}
	
	private void add_menu_sub(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=null;
		int menu_sub_size=0;
		String parent_key=el.getStr("parent_key");
		try {
			menu_sub_size = menu_sub_dao.size(wxproject_id,parent_key);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
		}
		if(menu_sub_size>=Keys.getInt("Max_Sub_Menu_Number")){
			msg=el.i18("menu.max.number.achieve");
		}
		if(msg!=null){
			el.setAttr("msg", msg);
			to_add_sub_page(el,wxproject_id);
			System.out.println("msg2:"+msg);
			return;
		}
		
		String key=UUID.randomUUID().toString();
		try {
			if(menu_sub_dao.exist(wxproject_id,parent_key,key)){
				msg=String.format(el.i18("menu.sub.exists"),parent_key, key);
				el.setAttr("msg", msg);
				to_add_sub_page(el,wxproject_id);
				return;
			}
		} catch (SQLException e1) {
			e1.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
			el.setAttr("msg", msg);
			to_add_sub_page(el,wxproject_id);
			return;
		}
		
		MenuSub menu=new MenuSub();
		menu.setParent_key(parent_key);
		menu.setKey(key);
		menu.setName(el.getStr("name"));
		menu.setType(el.getStr("type"));
		menu.setUrl(el.getStr("url"));
		menu.setWxproject_id(wxproject_id);
		try {
			menu.setPos(menu_sub_dao.getMaxPos(wxproject_id,parent_key));
			msg=validate(el, menu);
			if(msg==null){
				menu_sub_dao.insert(menu);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
			el.setAttr("msg", msg);
		}
		if(msg==null){
			msg=el.i18("menu.sub.add.success");
		}
		el.setAttr("msg",msg);
		load_menu_sub(el,wxproject_id);
	}
	
	private void to_add_sub_page(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String key=el.getStr("parent_key");
		String msg=el.getAttr("msg",null);
		Menu menu=null;
		try {
			menu=menu_dao.get(wxproject_id,key);
		} catch (SQLException e) {
			msg=el.i18("menu.db.failure");
			e.printStackTrace();
			el.setAttr("msg", msg);
		}
		el.setAttr("msg", msg);
		el.setAttr("menu", menu);
		el.template("/WEB-INF/template/boss/menu/menu_sub_add.vm");
		
	}
	
	
	private void load_menu(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String msg=el.getAttr("msg",null);
		List mlist=null;
		try {
			mlist=menu_dao.getAllByWxprojectId(wxproject_id);
		} catch (SQLException e) {
			msg=el.i18("menu.db.failure");
			e.printStackTrace();
			el.setAttr("msg", msg);
			el.template("/WEB-INF/template/boss/menu/index.vm");
			return;
		}
		
		List<MenuSub> slist=null;
		try {
			slist=menu_sub_dao.getAllByWxprojectId(wxproject_id);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.update.db_failure");
			log.error(msg, e);
			el.setAttr("msg", msg);
			el.template("/WEB-INF/template/boss/menu/index.vm");
			return;
		}
		
		if(slist==null||slist.isEmpty()){
			el.setAttr("msg", msg);
			el.setAttr("mlist", mlist);
			el.template("/WEB-INF/template/boss/menu/index.vm");
			return;
		}
		
		Iterator<Menu> itr=mlist.iterator();
		Menu cm=null;
		for(;itr.hasNext();){
			cm=itr.next();
			cm.setSubMenus(getSubMens(slist,cm.getKey()));
		}
		
		el.setAttr("msg", msg);
		el.setAttr("mlist", mlist);
		el.template("/WEB-INF/template/boss/menu/index.vm");
		
	}
	
	public void load_menu_sub(EventLoader el,long wxproject_id) throws IOException, ServletException{
		String key=el.getStr("parent_key");
		if(key==null){
			key=el.getStr("key");
		}
		String msg=el.getAttr("msg",null);
		List smlist=null;
		Menu menu=null;
		try {
			menu=menu_dao.get(wxproject_id,key);
		} catch (SQLException e) {
			msg=el.i18("menu.db.failure");
			e.printStackTrace();
			el.setAttr("msg", msg);
		}
		try {
			smlist=menu_sub_dao.getSubMenus(wxproject_id,key);
		} catch (SQLException e) {
			msg=el.i18("menu.sub.db.failure");
			e.printStackTrace();
		}
		
		try {
			Message message = auto_reply_dao.getCLICKMessage(wxproject_id,"type_msg",key);
			el.setAttr("reply_msg", message);
			List<MsgNews> list=auto_reply_news_dao.getNewsListByKey(wxproject_id,key);
			el.setAttr("reply_news", list);
		} catch (SQLException e) {
			e.printStackTrace();
			msg=el.i18("menu.sub.db.failure");
		}
		
		el.setAttr("msg", msg);
		el.setAttr("smlist", smlist);
		el.setAttr("menu", menu);
		el.template("/WEB-INF/template/boss/menu/menu_detail.vm");
		
	}

}
